最長合法字串問題
算法概論第八週
32. Longest Valid Parentheses — 題目鏈接
題目描述
Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.
Example 1:
Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"
Example 2:
Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"
思路分析
方法一:暴力枚舉
- 最樸素的方法就是把所有可能的長度都試一遍
- 每個長度都要從左至右找一遍字串驗證是否合法
- 判斷一個字串是否合法只需要維護一個棧,遇到(入棧,遇到)出棧,如果棧爲空仍然需要出棧,則返回false
- 複雜度:
- 時間:將所有長度試一遍爲,每個長度的所有字符串爲,棧判斷爲,一共爲
- 空間:維護一個棧爲
方法二:動態規劃
- 對於動態規劃,我們要找出它的最優子問題
- 設
dp[i]
爲以s[i]
結尾的最長合法字串的長度 - 那麼
dp[i]
的遞推式只有兩種情況s[i] == ')' && s[i-1] == '('
,則dp[i] = dp[i-2] + 2
s[i] == ')' && s[i-1] == ')' && s[i-dp[i-1]-1] == '('
,則dp[i] = dp[i-1] +dp[i-dp[i-1]-2] + 2
- 當然要注意檢查數組是否越界
- 從左至右遍歷,每一次用
dp[i]
更新最大值
- 複雜度:
- 時間:遍歷一遍即可得出所有值,
- 空間:用
dp
數組儲存,
方法三:計算左右括號
- 從左至右和從右至左分別遍歷
- 如果遇到左括號,
left++
,右括號,right++
,如果right > left
,清零 - 每一次迭代,如果
left == right
,更新最大值 - 需要兩個方向的遍歷原因是爲了計算類似
(((()
的情況 - 複雜度:
- 時間:
- 空間:僅
left
、right
,爲
代碼實現
方法一:暴力枚舉
TLE
class Solution {
public:
int longestValidParentheses(string s) {
int len = s.size();
int res = 0;
for(int i = 2; i <= len; i++){
for(int j = 0; j <= len - i; j++){
if(verifyString(s.substr(j, i))){
res = i;
break;
}
}
}
return res;
}
bool verifyString(string a){
int len = a.size();
stack <int> s;
for(int i = 0; i < len; i++){
if(a[i] == '(')
s.push(1);
else{
if(!s.empty())
s.pop();
else
return false;
}
}
return s.empty();
}
};
方法二:動態規劃
AC 超過61.92%的cpp程序
class Solution {
public:
int longestValidParentheses(string s) {
int len = s.size();
if(len < 2)
return 0;
int* dp = new int[len];
int res = 0;
for(int i = 0; i < len; i++){
dp[i] = 0;
}
for(int i = 1; i < len; i++){
if(s[i] == ')' && s[i-1] == '('){
dp[i] = ((i-2 >= 0) ?dp[i-2] : 0) + 2;
}
else if(s[i] == ')' && s[i-1] == ')'){
if(i - dp[i-1] - 1 >= 0 && s[i-dp[i-1]-1] == '('){
dp[i] = dp[i-1] + ((i-dp[i-1]-2 >= 0) ? dp[i-dp[i-1]-2]:0) + 2;
}
}
res = max(res, dp[i]);
}
return res;
}
};
方法三:計算左右括號
AC 超過99.93%的cpp程序
class Solution {
public:
int longestValidParentheses(string s) {
int left = 0, right = 0, maxlength = 0;
for (int i = 0; i < s.length(); i++) {
if (s[i] == '(') {
left++;
} else {
right++;
}
if (left == right) {
maxlength = max(maxlength, 2 * right);
} else if (right >= left) {
left = right = 0;
}
}
left = right = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s[i] == '(') {
left++;
} else {
right++;
}
if (left == right) {
maxlength = max(maxlength, 2 * left);
} else if (left >= right) {
left = right = 0;
}
}
return maxlength;
}
};